home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / mp_widgets.pro < prev    next >
Text File  |  1997-07-08  |  12KB  |  375 lines

  1. ; $Id: mp_widgets.pro,v 1.6 1997/01/15 03:11:50 ali Exp $
  2.  
  3. ; Copyright (c) 1990-1997, Research Systems, Inc.  All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;    MP_WIDGETS
  8. ;
  9. ; PURPOSE:
  10. ;    Provide a graphical user interface to the online documentation.
  11. ;    The topic is selected by pressing a button at the top.
  12. ;    Subtopics a displayed in a scrolling list on the left side.  Pressing
  13. ;    a mouse button while pointing at a subtopic causes the information
  14. ;    on that topic to be displayed in the large text region on the right.
  15. ;
  16. ;    It is expected that this routine will only be called by MAN_PROC.
  17. ;
  18. ; CATEGORY:
  19. ;    Help, documentation, widgets.
  20. ;
  21. ; CALLING SEQUENCE:
  22. ;    MP_WIDGETS [, Request]
  23. ;
  24. ; INPUTS:
  25. ;     Request:    A scalar string containing the item on which help is desired.
  26. ;        This string can contain 1 or two (whitespace separated) words.
  27. ;        The first word is taken as the global topic and the second
  28. ;        as the topic within the scope of the first.
  29. ;
  30. ; OUTPUTS:
  31. ;    None.  A widget interface is used to allow reading the help text.
  32. ;
  33. ; COMMON BLOCKS:
  34. ;    MPW_COM: This common block is private to MP_WIDGETS, and
  35. ;         should not be referenced by other modules.
  36. ;
  37. ; RESTRICTIONS:
  38. ;    The basic version of the help facility (MP_BASIC) can accept
  39. ;    ambiguous requests, and if a request maches more than a single
  40. ;    subtopic, they are all shown.  This version can also accept
  41. ;    ambiguous requests, but only the first subtopic matched is shown.
  42. ;    This feature is not as important as it was in MP_BASIC because the
  43. ;    widget interface allows multiple subjects to be viewed easily.
  44. ;
  45. ;    This routine uses a COMMON block to keep its internal state, so only
  46. ;    one copy of this routine can run at a time.
  47. ;
  48. ; MODIFICATION HISTORY:
  49. ;    AB, August, 1990
  50. ;    28 December 1990    Rewritten to take advantages in changes to
  51. ;                the widget facility, to use XMANAGER, and to
  52. ;                accept the REQUEST argument.
  53. ;    31 December 1992    Modified to ignore the optional %TITLE
  54. ;                line at the top of the file. There's no
  55. ;                reason to handle it, since this routine is
  56. ;                obsolete. The builtin online help system
  57. ;                *does* handle it.
  58. ;-
  59.  
  60.  
  61.  
  62.  
  63. function mpw_set_lv1, topic_idx, lv2_topics
  64. ; Open a new level 1 help file. Close the old one if one exists.
  65. ; Update the common block to reflect the change. lv2_topics is the
  66. ; array of level 2 topics found in the file. Returns TRUE if the topic
  67. ; was changed, FALSE otherwise.
  68.  
  69. common mpw_com, cur_lv1_topic_idx, cur_lv2_idx, offsets, text_base, list, $
  70.     title, text, unit, lv1_topics, lv1_files
  71.  
  72.   if (topic_idx ne cur_lv1_topic_idx) then begin   ; Only if the topic changed.
  73.     if (unit ne 0) then FREE_LUN, unit
  74.     openr, unit, lv1_files[topic_idx], /get_lun
  75.     cur_lv1_topic_idx = topic_idx
  76.     n = 0L
  77.     tmp = ''
  78.     readf, unit, tmp
  79.     ; If it's the version tag, parse it.
  80.     version = 1L                    ; Assume old format
  81.     if (strmid(tmp, 0, 9) eq '%VERSION:') then begin
  82.       reads, tmp, version, format='(9X, I0)'
  83.       readf,unit,tmp                ; Read next line.
  84.     endif
  85.     if (strmid(tmp, 0, 7) eq '%TITLE:') then readf, unit, tmp    ; Skip title
  86.     n = long(tmp)                ; # of records
  87.     if (version ne 1) then begin
  88.       ; Version 2 format has the number of characters used by all the
  89.       ; subtopics on the next line. We don't use it, but have to read it
  90.       readf,unit,tmp                ; Read next line.
  91.     endif
  92.     lv2_topics = strarr(n)            ;Make names
  93.     readf, unit, lv2_topics            ;Read entire string from unit
  94.     if (version eq 1) then begin
  95.       offsets = long(strmid(lv2_topics, 15, 30))    ;Extract starting bytes
  96.       lv2_topics = strmid(lv2_topics,0,15)        ;Isolate names
  97.     endif else begin
  98.       offsets = lonarr(n)
  99.       for i = 0, n-1 do begin
  100.         tmp = lv2_topics[i]
  101.         colon = strpos(tmp, ':') + 1        ; Find delimiter
  102.         offsets[i] = long(strmid(tmp, 0, colon))
  103.         lv2_topics[i] = strmid(tmp, colon, 10000000)
  104.       endfor
  105.     endelse
  106.  
  107.     ; Determine the base of the help text
  108.     tmp = fstat(unit)
  109.     text_base = tmp.cur_ptr
  110.     cur_lv2_idx=-1
  111.     r = 1
  112.   endif else r = 0
  113.  
  114.   return, r
  115. end
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123. pro mpw_update_display, lv2_topics
  124. ; Update the topic label and list elements to reflect the current state
  125. ; as determined by mpw_set_lv1. lv2_topics is the array of level 2 topics
  126. ; returned by mpw_set_lv1.
  127.  
  128.   common mpw_com, cur_lv1_topic_idx, cur_lv2_idx, offsets, text_base, list, $
  129.     title, text, unit, lv1_topics, lv1_files
  130.  
  131.   WIDGET_CONTROL, list, set_value=lv2_topics
  132.   WIDGET_CONTROL,title,set_value='Current Topic: ' $
  133.     + lv1_topics[cur_lv1_topic_idx]
  134.   WIDGET_CONTROL,text,set_value='', /NO_NEWLINE
  135.  
  136. end
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144. pro mpw_set_lv2, index
  145. ; Given an index, display the text associated with it in the current
  146. ; help file.
  147.  
  148.   common mpw_com, cur_lv1_topic_idx, cur_lv2_idx, offsets, text_base, list, $
  149.     title, text, unit, lv1_topics, lv1_files
  150.  
  151.   if (cur_lv2_idx ne index) then begin
  152.     str = ''
  153.     POINT_LUN, unit, text_base + offsets[index]
  154.     readf, unit, str                ; Skip the ";+"
  155.     ; Remember this position
  156.     start = fstat(unit)
  157.     start = start.cur_ptr
  158.     ; Find the end
  159.     while (str NE ";-") do readf, unit, str
  160.     ; How long is the selection?
  161.     tmp = fstat(unit)
  162.     len = tmp.cur_ptr - start - 3
  163.     ; Read the text using binary I/O into a single byte array for efficiency
  164.     str = bytarr(len)
  165.     point_lun, unit, start
  166.     readu, unit, str
  167.     WIDGET_CONTROL, text, SET_VALUE=string(str), /NO_NEWLINE
  168.     cur_lv2_idx = index
  169.   endif
  170.  
  171. end
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. pro mpw_event, ev
  180.  
  181. common mpw_com, cur_lv1_topic_idx, cur_lv2_idx, offsets, text_base, list, $
  182.     title, text, unit, lv1_topics, lv1_files
  183.  
  184.   case (tag_names(ev, /STRUCTURE_NAME)) of
  185.   "WIDGET_BUTTON": begin
  186.       WIDGET_CONTROL, get_uvalue=uv, ev.id
  187.       if (uv eq -2) then begin
  188.         WIDGET_CONTROL, /DESTROY, ev.top
  189.         if (unit ne 0) then FREE_LUN, unit
  190.         return
  191.       endif else begin
  192.         if (mpw_set_lv1(uv,lv2_topics)) then mpw_update_display,lv2_topics
  193.       endelse
  194.     end
  195.   "WIDGET_LIST": mpw_set_lv2, ev.index
  196.   endcase
  197.  
  198.  
  199. end
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207. function MPW_TM, KEY, TOPIC_ARRAY
  208. ; Topic Matcher. Given KEY, this routine returns an index into TOPIC_ARRAY
  209. ; that matches KEY. If there is an exact match, that index is returned.
  210. ; otherwise the first element with the same prefix is returned.
  211. ; On error, MESSAGE is used to report the problem and terminate execution.
  212.  
  213.   found = where(STRTRIM(TOPIC_ARRAY) eq KEY, count) ; Match exact string
  214.   if (count le 0) then begin    ; No exact match, try to match the prefix
  215.     FOUND = where(strpos(TOPIC_ARRAY, KEY) eq 0, count)
  216.     if (count le 0) then begin
  217.       message, /NONAME, 'Unknown topic: ' + KEY
  218.     endif else begin
  219.       if (count ne 1) then begin
  220.     message, /INFO, /NONAME, 'Ambiguous topic "' + KEY $
  221.         + '" matches: ' + string(format='(i0, " ")', count) $
  222.         + 'items. ' + strcompress(topic_array[found[0]], /remove) $
  223.         + ' used.'
  224.       endif
  225.     endelse
  226.   endif
  227.  
  228.   return, found[0]
  229. end
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237. pro MP_WIDGETS, request
  238.  
  239.   common mpw_com, cur_lv1_topic_idx, cur_lv2_idx, offsets, text_base, list, $
  240.     title, text, unit, lv1_topics, lv1_files
  241.  
  242.   if (XREGISTERED('MP_WIDGETS')) then return    ; Only one copy at a time
  243.  
  244.   on_error, 1        ; On error, return to main level
  245.   unit = 0        ; No help file is open yet
  246.  
  247.   ; lv1_files recieves all help files found through !HELP_PATH.
  248.   lv1_dirs = EXPAND_PATH(!HELP_PATH, /ARRAY, COUNT=cnt)
  249.   if (cnt eq 0) then message, 'No online help files found.'
  250.   for i = 0, cnt-1 do begin
  251.     tmp = STRLOWCASE(findfile(filepath('*.help', root_dir=lv1_dirs[i])))
  252.     if (i eq 0) then lv1_files = TEMPORARY(tmp) $
  253.     else lv1_files=[lv1_files, TEMPORARY(tmp)]
  254.   endfor
  255.  
  256.   ; lv1_topics gets uppercase version of just the names.
  257.   lv1_topics = STRUPCASE(lv1_files)
  258.   if !version.os ne 'Win32' then begin
  259.     tail = STRPOS(lv1_topics, '.HELP')
  260.   endif else begin
  261.     tail = STRPOS(lv1_topics, '.HEL')
  262.   endelse
  263.   n = n_elements(lv1_topics)
  264.   for i = 0, n-1 do $
  265.     lv1_topics[i] = strmid(lv1_topics[i], 0, tail[i])
  266.   for i = 0, n-1 do begin    ; Strip path part off lv1_topics
  267.     case !version.os of
  268.       'vms': begin
  269.            j = STRPOS(lv1_topics[i], ']')
  270.            while (j ne -1) do begin
  271.              lv1_topics[i] = strmid(lv1_topics[i], j+1, 32767)
  272.              j = STRPOS(lv1_topics[i], ']')
  273.            endwhile
  274.       end
  275.       'Win32': begin
  276.         j = STRPOS(lv1_topics[i], '\')
  277.         while (j ne -1) do begin
  278.         lv1_topics[i] = strmid(lv1_topics[i], j+1, 32767)
  279.           j = STRPOS(lv1_topics[i], '\')
  280.         endwhile
  281.       end
  282.       'MacOS': begin
  283.         j = STRPOS(lv1_topics[i], ':')
  284.         while (j ne -1) do begin
  285.         lv1_topics[i] = strmid(lv1_topics[i], j+1, 32767)
  286.           j = STRPOS(lv1_topics[i], ':')
  287.         endwhile
  288.       end
  289.       else:  begin      ; Unix otherwise
  290.         j = STRPOS(lv1_topics[i], '/')
  291.         while (j ne -1) do begin
  292.         lv1_topics[i] = strmid(lv1_topics[i], j+1, 32767)
  293.           j = STRPOS(lv1_topics[i], '/')
  294.         endwhile
  295.       end
  296.     endcase
  297.   endfor
  298.  
  299.   ; Sort the topics into alphabetical order.
  300.   tmp = sort(lv1_topics)
  301.   lv1_files = lv1_files[tmp]
  302.   lv1_topics = lv1_topics[tmp]
  303.  
  304.  
  305.   ; Check the request (if any) for validity before any widgets are created.
  306.   ; If it is empty, act as if it isn't present.
  307.   REQ_PRESENT = N_ELEMENTS(REQUEST) ne 0
  308.   if (REQ_PRESENT) then begin
  309.     temp = size(request)
  310.     if (temp[0] NE 0) then message, 'Argument must be scalar.'
  311.     if (temp[1] NE 7) then message, 'Argument must be of type string.'
  312.     if (STRLEN(STRCOMPRESS(REQUEST, /REMOVE_ALL)) eq 0) then REQ_PRESENT = 0
  313.   endif
  314.  
  315.   ; Choose initial display using first option in this list that fits:
  316.   ;  - Request on the command line.
  317.   ;  - The topic used last time this routine was run.
  318.   ;  - Topic is ROUTINES, subtopic is empty
  319.   if (REQ_PRESENT) then begin
  320.     ; Parse into 1 or two strings
  321.     lv1_topic_idx = STRUPCASE(STRTRIM(STRCOMPRESS(REQUEST), 2))
  322.     if (((blank_pos = STRPOS(lv1_topic_idx, ' '))) ne -1) then begin
  323.       lv2_topic = STRMID(lv1_topic_idx, blank_pos+1, 10000L)
  324.       lv1_topic_idx = STRMID(lv1_topic_idx, 0, blank_pos)
  325.     endif else begin
  326.       lv2_topic=''
  327.     endelse
  328.     ; Make sure its legitimate.
  329.     lv1_topic_idx = MPW_TM(lv1_topic_idx, lv1_topics)
  330.     cur_lv1_topic_idx = -1
  331.     junk = mpw_set_lv1(lv1_topic_idx, lv2_topics)
  332.     if (lv2_topic ne '') then lv2_index = MPW_TM(lv2_topic, lv2_topics) $
  333.       else lv2_index = -1
  334.   endif else begin            ; No request is present
  335.     if (n_elements(cur_lv1_topic_idx) eq 0) then begin    ; Default to ROUTINES
  336.       lv1_topic_idx=MPW_TM("ROUTINES", lv1_topics)    ; No sub-topic
  337.       lv2_index = -1
  338.     endif else begin                    ; Use previous state
  339.       lv1_topic_idx=cur_lv1_topic_idx
  340.       lv2_index = cur_lv2_idx
  341.     endelse
  342.     cur_lv1_topic_idx = -1
  343.     junk = mpw_set_lv1(lv1_topic_idx, lv2_topics)
  344.   endelse
  345.   cur_lv2_idx = -1                ; Forget the old state
  346.  
  347.   ; The request (if any) is OK. Create and realize the widgets.
  348.   base = WIDGET_BASE(title='Help', /COLUMN)
  349.   cntl1 = WIDGET_BASE(base, /FRAME, /ROW, space=30)
  350.   if (!version.os eq 'sunos') then tmp = 10 else tmp = 5
  351.   cntl2 = WIDGET_BASE(base, column=tmp, /FRAME, /exclusive)
  352.     pb_quit = WIDGET_BUTTON(value='Quit', cntl1, uvalue = -2)
  353.     topic_but_ids = lonarr(n, /nozero)
  354.     for i = 0, n-1 do $
  355.       topic_but_ids[i] = WIDGET_BUTTON(value=lv1_topics[i], cntl2, $
  356.                     uvalue = i, /NO_RELEASE)
  357.   title=WIDGET_LABEL(cntl1, value='Current Topic:')
  358.   bottom=WIDGET_BASE(base, /ROW)
  359.   list = WIDGET_LIST(bottom,ysize=30,value = string(bytarr(20) + 45B),/frame)
  360.   text = WIDGET_TEXT(bottom, /SCROLL, xsize = 80, ysize=45)
  361.  
  362.   WIDGET_CONTROL, base, /REALIZE
  363.  
  364.   mpw_update_display, lv2_topics
  365.  
  366.   ; Set the proper button
  367.   if (cur_lv1_topic_idx ne -1) then $
  368.     WIDGET_CONTROL, topic_but_ids[cur_lv1_topic_idx], /SET_BUTTON
  369.  
  370.   lv2_topics = 0        ; Free the dynamic memory
  371.   if (lv2_index ne -1) then mpw_set_lv2, lv2_index
  372.  
  373.   XMANAGER, 'MP_WIDGETS', base, event_handler='MPW_EVENT', /NO_BLOCK
  374. end
  375.